package com.lagou.edu.utils;

import com.lagou.edu.anno.Autowired;
import com.lagou.edu.anno.Repository;
import com.lagou.edu.anno.Service;
import com.lagou.edu.anno.Transactional;
import com.lagou.edu.factory.ProxyFactory;

import java.io.File;
import java.lang.reflect.Field;

import java.util.*;

/**
 * 处理注解类
 */
public class AnnotationUtils {

    /**
     * bean 容器创建
     */
    private static Map<String,Object> map;

    public static Map<String,Object>  getMap( String id) {
        return map;
    }

    /**
     * 实例化容器bean
     */

   static{
        try {
            getAllBeansToMap();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    /**
     * 获取此工程所有的bean存储到容器中
     * @throws Exception
     */
    private static void getAllBeansToMap() throws Exception {
        map = new HashMap<>();
        getClassFileName();
    }

    /**
     * 根据类的全路径名称获取该类的反射对象注入并放入map,然后进行属性注入。
     */

    private static void getClassFileName() throws Exception {
           List<String> listClass = getClassName();
            for (String aClass : listClass) {
                setMap(aClass);
            }
        for (Map.Entry<String, Object> aClass : map.entrySet()) {
            if(aClass.getKey().equals("transferServiceImpl")){
                System.out.println();
            }
            if (aClass!=null) {
                autowired(aClass.getValue());
                transaction(aClass.getValue());

            }
        }




    }
    /**
     * 将带有@Service,或者Repository初始化到容器,如果为Transactionl则需要处理其代理对象。
     * @param name
     * @throws Exception
     */
    private static void setMap (String name) throws Exception {
        System.out.println(name);
        if("com.lagou.edu.servlet.TransferServlet".equals(name)){
            System.out.println();
        }
        Class<?> cla = Class.forName(name);
        Repository bean = cla.getAnnotation(Repository.class);
        Service service = cla.getAnnotation(Service.class);
        if(service != null){
            map.put(tolowerBeanName(cla.getSimpleName()), cla.newInstance());
        }
        if (bean != null) {
            map.put(tolowerBeanName(cla.getSimpleName()), cla.newInstance());
        }
    }
    /**
     * 处理transaction注解是的思路
     * @param object
     */
    private static void transaction(Object object) throws ClassNotFoundException {
        Class<?> objectClass = object.getClass();
        Transactional annotation = objectClass.getAnnotation(Transactional.class);
        if(annotation!=null){
            ProxyFactory proxyFactory =(ProxyFactory)map.get("proxyFactory");
            Object jdkProxy = proxyFactory.getJdkProxy(object);
            String beanId = objectClass.getSimpleName();
            String beanName = tolowerBeanName(beanId);
            map.put(beanName,jdkProxy);
            //首字母强制转小写然后覆盖之前的对象

        }
    }
    /**
     * autowired 注解注入
     */
    public static void autowired( Object object) throws Exception {
        Class<?> clazz = object.getClass();
        Field[] fields = clazz.getDeclaredFields();
        System.out.println("访问类的类名"+clazz.getSimpleName());
        for (Field field : fields) {
            field.setAccessible(true);
            System.out.println("字段名字"+field.getName());

            if(field.getName().equals("accountDao")){
                System.out.println();
            }
            Autowired annotation = field.getAnnotation(Autowired.class);
            if(annotation!=null){
/*
                ServiceLoader<?> load = ServiceLoader.load(field.getType());
                //获取当前实现类的类名
                String simpleName = load.findFirst().get();
                String value = tolowerBeanName(simpleName);*/
                try {
                   Object obj =  map.get(annotation.value());
                    field.set(object,obj);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }

            }
        }
    }


    /**
     * 获取当前项目的多有java文件
     * @throws Exception
     */
    private static List<String> getClassName() throws Exception {
        // 获取到此项目的src路径
        String path = "D:\\codeProjects\\lagou-transfer" + "\\src";
        List<String> listname = new ArrayList<String>();
        List<String> classFileName = getClassFileName(path, listname);
        return classFileName;
    }

    /**
     * 获取目录下的java 文件
     * @param filepath
     * @param listname
     * @return
     * @throws Exception
     */
    private static List<String> getClassFileName(String filepath ,List<String> listname) throws Exception {
        File file= new File(filepath);
        if(file.isDirectory()){
            String[] filelist=file.list();
            for(int i = 0;i<filelist.length;i++){
                File readfile = new File(filepath+"\\"+filelist[i]);
                if (!readfile.isDirectory()) {
                    if((filepath+"\\"+filelist[i]).endsWith("java")){
                        String  str = (filepath+"\\"+filelist[i]).replace("\\",".");
                        String classCz = str.substring(str.indexOf("java.", 1)+5);
                        classCz = classCz.substring(0, classCz.length() - 5);
                        listname.add(classCz);

                    }
                } else if (readfile.isDirectory()) {
                   getClassFileName(filepath + "\\" + filelist[i],listname);
                }
            }

        }

        return listname;

    }


    //处理beanName;
    private static String tolowerBeanName(String beanName){
        String first = beanName.substring(0, 1).toLowerCase();
        String beanStr = first+beanName.substring(1);
        return beanStr;
    }

}